#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define  IO_BASE_P 	0x80840000
#define  DR_OFFSET 	0
#define  DDR_OFFSET 	0x10
#define  CTL_DR_OFFSET 	0x40 
#define  CTL_DDR_OFFSET 0x44

#define HD44780_HAS_DDR 
#include "hd44780_engine.h"

int main(){

	volatile unsigned char * PADR_p;
	volatile unsigned char * PADDR_p;
	volatile unsigned char * PHDR_p;
	volatile unsigned char * PHDDR_p;

	int fd = open( "/dev/mem" , O_RDWR | O_SYNC);
	if( -1 == fd ){
		fprintf( stderr , "open() function failed !!!\n");
		abort();
	}

	unsigned char * io_mapped_p = mmap( 0 , getpagesize() , PROT_READ|PROT_WRITE , MAP_SHARED , fd , IO_BASE_P );
	if( (void *)-1 == io_mapped_p  ){
		fprintf( stderr , "mmap() function failed !!!\n");
		abort();
	}
	int i;
	PADR_p	= io_mapped_p + DR_OFFSET;
	PADDR_p	= io_mapped_p + DDR_OFFSET;
	PHDR_p	= io_mapped_p + CTL_DR_OFFSET;
	PHDDR_p	= io_mapped_p +CTL_DDR_OFFSET;

	/* initialization of hd44780 */
	HD44780_INIT( PADR_p , PADDR_p , PHDR_p , PHDDR_p );
#if 0
	HD44780_FUNC_display_on_off_control( 1 , 1 , 0 );

	DD_ADDR  dd_addr = {0}; 
	HD44780_FUNC_set_ddram_addr( dd_addr );

	for(i=0 ; i<40 ;i++){
		HD44780_FUNC_set_ddram_addr( dd_addr );
		OCTER read_char;
		read_char = HD44780_FUNC_read_data();
			
		printf("***** %02d: %02d %c --- %d *****\n" , i , read_char.byte , read_char.byte , dd_addr.DDA.byte );
		dd_addr.DDA.byte++;
	}


	HD44780_FUNC_display_on_off_control( 1 , 1 , 1 );

	OCTER display_char;
	dd_addr.DDA.byte = 0;
	HD44780_FUNC_set_ddram_addr( dd_addr );
	char begin_char = 'A';

	for( i=0 ; i<20 ; i++){
			
		dd_addr.DDA.byte = i*2;
		HD44780_FUNC_set_ddram_addr( dd_addr );
		unsigned char write_char = (begin_char + i - 'A') % 26 + 'A';
		display_char.byte =  write_char ;
		HD44780_FUNC_write_data( display_char );
	}
	if( 'Z' < begin_char ){
		begin_char = 'A';
	}

	begin_char ++;
	i=40;

/*	while(i--){
		HD44780_FUNC_cursor_display_shift( 1 , 1 );
		usleep(500 * 1000);
	}
*/
	printf("+++++++++++++++++++++++++++++++\n");
	HD44780_FUNC_return_home();
	dd_addr.DDA.byte = 0;
	for(i=0 ; i<40 ;i++){
		HD44780_FUNC_set_ddram_addr( dd_addr );
		OCTER read_char;
		read_char = HD44780_FUNC_read_data();
			
		printf("***** %02d: %02d %c --- %d *****\n" , i , read_char.byte , read_char.byte , dd_addr.DDA.byte );
		dd_addr.DDA.byte++;
	}

	HD44780_FUNC_read_bf_ac();

	HD44780_FUNC_cursor_display_shift( 1 , 0 );
	HD44780_FUNC_cursor_display_shift( 1 , 0 );
	HD44780_FUNC_cursor_display_shift( 1 , 0 );
	HD44780_FUNC_cursor_display_shift( 1 , 0 );
	sleep(4);

	HD44780_FUNC_clear_display();	
/*
	CG_ADDR cf_addr = {0};
	HD44780_FUNC_set_cgram_addr( cf_addr );

	OCTER data[8] = { 0 };
	SET_OCTER_BY_BITS( data[0] , 00000);
	SET_OCTER_BY_BITS( data[1] , 00100);
	SET_OCTER_BY_BITS( data[2] , 01010);
	SET_OCTER_BY_BITS( data[3] , 10101);
	SET_OCTER_BY_BITS( data[4] , 01010);
	SET_OCTER_BY_BITS( data[5] , 00100);
	SET_OCTER_BY_BITS( data[6] , 00000);
	SET_OCTER_BY_BITS( data[7] , 00000);

	int j;
	for( j=0 ; j<8 ;j++ ){
		HD44780_FUNC_write_data( data[j] );
	}

	dd_addr.DDA.byte =0;
	HD44780_FUNC_set_ddram_addr( dd_addr );
	data[0].byte = 0x0;
	HD44780_FUNC_write_data( data[0] );
	data[0].byte = 0x1;
	HD44780_FUNC_write_data( data[0] );
*/
	unsigned char string[20]={0}; 
	memcpy(string, "abcde1234567890abcde",20);
	HD44780_SET_LINE_TEXT( 1 , string );	
	memcpy(string , "12345abcdefghij12345" , 20);
	HD44780_SET_LINE_TEXT( 0 , string );	
#endif
//	while(1){	
//		fill_line_content( FIRST_LINE , "< " , "hello hello hello hello hello " ," >" , -1 , false );
		fill_line_content( FIRST_LINE , "<" , "hello" ,">" , -2 , false  , CENTERED );
		fill_line_content( SECOND_LINE , ">  " , "world1234567890-+" , "  <" , -3 , false , ALIGN_RIGHT );
	while(1){
		scroll_display( FIRST_LINE);
		scroll_display( SECOND_LINE);
		sleep(1);
	}

	/* clear up the environment */
	if( -1 == munmap( io_mapped_p , getpagesize() ) ){
		fprintf( stderr , "munmap() function failed !!!\n") ;
		abort();
	}
	close( fd );

	return 0;
}
